From 444685b1018b15b5037467e7d6a8fab4801a236e Mon Sep 17 00:00:00 2001
From: "oussama.aftys" <oussama.aftys@marketingconfort.com>
Date: Mon, 29 Jul 2024 18:13:44 +0100
Subject: [PATCH] optimize live product timestamps management

---
 .dockerignore                                 |  46 +++
 .env                                          |   4 +-
 next.config.mjs                               |  14 +-
 package-lock.json                             |  45 +++
 package.json                                  |   1 +
 src/components/copy-button.tsx                |   7 +-
 src/config-global.ts                          |   2 +
 src/hooks/use-async.ts                        |  27 ++
 src/hooks/use-live-comments.ts                |   5 +-
 src/shared/api/live.ts                        | 233 ++++++++-----
 src/shared/api/server.ts                      |  61 +++-
 .../notification-item.tsx                     |   2 +-
 .../lives/add-edit-live/add-live-view.tsx     |  52 +--
 .../lives/all-lives/live-table-row.tsx        | 256 +++++++--------
 src/shared/sections/lives/details/view.tsx    | 137 ++++----
 .../supervision/details-comments-input.tsx    |   2 +-
 .../supervision/details-comments-item.tsx     |  26 +-
 .../supervision/details-comments-list.tsx     |  73 +++--
 .../supervision/details-comments-section.tsx  |   5 +-
 .../supervision/details-player-section.tsx    |  60 +++-
 .../supervision/details-product-card.tsx      | 306 +++++++++++-------
 .../supervision/details-products-section.tsx  |   4 +-
 .../sections/lives/supervision/view.tsx       |   8 +-
 src/shared/types/live.ts                      |  11 +-
 24 files changed, 881 insertions(+), 506 deletions(-)
 create mode 100644 .dockerignore
 create mode 100644 src/hooks/use-async.ts

diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 00000000..96f888bb
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,46 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+.yarn/install-state.gz
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# local env files
+.env*.local
+
+# vercel
+.vercel
+
+# typescript
+*.tsbuildinfo
+next-env.d.ts
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+.env
+
+### VS Code ###
+.vscode/
diff --git a/.env b/.env
index c20eeb49..8b729873 100644
--- a/.env
+++ b/.env
@@ -1,8 +1,8 @@
 # HOST
 NEXT_PUBLIC_HOST_API=https://api-dev-minimal-v510.vercel.app
 
-NEXT_PUBLIC_HOST_API_URL=https://mydressin-stream-service.mc-test.xyz
-NEXT_PUBLIC_WEB_SOCKET_URL=https://mydressin-stream-service.mc-test.xyz/ws
+NEXT_PUBLIC_HOST_API_URL=http://15.237.175.171:8080
+NEXT_PUBLIC_WEB_SOCKET_URL=http://15.237.175.171:8080/ws
 
 # ASSETS
 NEXT_PUBLIC_ASSETS_API=https://api-dev-minimal-v510.vercel.app
diff --git a/next.config.mjs b/next.config.mjs
index c3bec89a..58f9c664 100644
--- a/next.config.mjs
+++ b/next.config.mjs
@@ -1,6 +1,18 @@
 /** @type {import('next').NextConfig} */
+import { resolve } from 'path';
+
 const nextConfig = {
-    
+  webpack: (config, { isServer }) => {
+    // Ensure inherits is properly resolved
+    config.resolve.fallback = {
+      ...config.resolve.fallback,
+      inherits: resolve('node_modules/inherits/inherits_browser.js'),
+    };
+
+    // Additional custom webpack configurations can go here
+
+    return config;
+  },
 };
 
 export default nextConfig;
diff --git a/package-lock.json b/package-lock.json
index 8d5b4bf2..bce6958a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -76,6 +76,7 @@
       },
       "devDependencies": {
         "@types/autosuggest-highlight": "^3.2.3",
+        "@types/json2csv": "^5.0.7",
         "@types/node": "20.11.30",
         "@types/nprogress": "^0.2.3",
         "@types/react": "18.2.70",
@@ -1859,6 +1860,11 @@
       "resolved": "https://registry.npmjs.org/@stomp/stompjs/-/stompjs-7.0.0.tgz",
       "integrity": "sha512-fGdq4wPDnSV/KyOsjq4P+zLc8MFWC3lMmP5FBgLWKPJTYcuCbAIrnRGjB7q2jHZdYCOD5vxLuFoKIYLy5/u8Pw=="
     },
+    "node_modules/@streamparser/json": {
+      "version": "0.0.6",
+      "resolved": "https://registry.npmjs.org/@streamparser/json/-/json-0.0.6.tgz",
+      "integrity": "sha512-vL9EVn/v+OhZ+Wcs6O4iKE9EUpwHUqHmCtNUMWjqp+6dr85+XPOSGTEsqYNq1Vn04uk9SWlOVmx9J48ggJVT2Q=="
+    },
     "node_modules/@swc/helpers": {
       "version": "0.5.2",
       "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.2.tgz",
@@ -1956,6 +1962,15 @@
         "hoist-non-react-statics": "^3.3.0"
       }
     },
+    "node_modules/@types/json2csv": {
+      "version": "5.0.7",
+      "resolved": "https://registry.npmjs.org/@types/json2csv/-/json2csv-5.0.7.tgz",
+      "integrity": "sha512-Ma25zw9G9GEBnX8b12R4EYvnFT6dBh8L3jwsN5EUFXa+fl2dqmbLDbNWN0XuQU3rSXdsbBeCYjI9uHU2PUBxhA==",
+      "dev": true,
+      "dependencies": {
+        "@types/node": "*"
+      }
+    },
     "node_modules/@types/lodash": {
       "version": "4.14.202",
       "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.202.tgz",
@@ -4890,6 +4905,31 @@
       "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
       "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="
     },
+    "node_modules/json2csv": {
+      "version": "6.0.0-alpha.2",
+      "resolved": "https://registry.npmjs.org/json2csv/-/json2csv-6.0.0-alpha.2.tgz",
+      "integrity": "sha512-nJ3oP6QxN8z69IT1HmrJdfVxhU1kLTBVgMfRnNZc37YEY+jZ4nU27rBGxT4vaqM/KUCavLRhntmTuBFqZLBUcA==",
+      "dependencies": {
+        "@streamparser/json": "^0.0.6",
+        "commander": "^6.2.0",
+        "lodash.get": "^4.4.2"
+      },
+      "bin": {
+        "json2csv": "bin/json2csv.js"
+      },
+      "engines": {
+        "node": ">= 12",
+        "npm": ">= 6.13.0"
+      }
+    },
+    "node_modules/json2csv/node_modules/commander": {
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
+      "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
+      "engines": {
+        "node": ">= 6"
+      }
+    },
     "node_modules/json5": {
       "version": "2.2.3",
       "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
@@ -5054,6 +5094,11 @@
       "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
       "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g=="
     },
+    "node_modules/lodash.get": {
+      "version": "4.4.2",
+      "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
+      "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ=="
+    },
     "node_modules/lodash.groupby": {
       "version": "4.6.0",
       "resolved": "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz",
diff --git a/package.json b/package.json
index e819a22e..07547707 100644
--- a/package.json
+++ b/package.json
@@ -77,6 +77,7 @@
   },
   "devDependencies": {
     "@types/autosuggest-highlight": "^3.2.3",
+    "@types/json2csv": "^5.0.7",
     "@types/node": "20.11.30",
     "@types/nprogress": "^0.2.3",
     "@types/react": "18.2.70",
diff --git a/src/components/copy-button.tsx b/src/components/copy-button.tsx
index f6ae035a..00ad37f6 100644
--- a/src/components/copy-button.tsx
+++ b/src/components/copy-button.tsx
@@ -1,6 +1,7 @@
 import React from 'react';
 import { IconButton, SxProps, Theme, Tooltip } from '@mui/material';
 import ContentCopyIcon from '@mui/icons-material/ContentCopy';
+import { useSnackbar } from '@/shared/components/snackbar';
 
 interface CopyButtonProps {
   value: string;
@@ -8,13 +9,15 @@ interface CopyButtonProps {
 }
 
 const CopyButton: React.FC<CopyButtonProps> = ({ value, sx }) => {
+  const {enqueueSnackbar} = useSnackbar();
   const handleCopy = () => {
     navigator.clipboard.writeText(value)
       .then(() => {
-        console.log('Copied to clipboard');
+        enqueueSnackbar('Copied to clipboard', {variant: 'success'});
       })
       .catch(err => {
-        console.error('Failed to copy: ', err);
+        console.error(err);
+        enqueueSnackbar('Failed to copy to clipboard', {variant: 'error'});
       });
   };
 
diff --git a/src/config-global.ts b/src/config-global.ts
index 8964baca..e833250b 100644
--- a/src/config-global.ts
+++ b/src/config-global.ts
@@ -5,6 +5,8 @@ import { paths } from '@/routes/paths';
 
 export const HOST_API = process.env.NEXT_PUBLIC_HOST_API;
 export const ASSETS_API = process.env.NEXT_PUBLIC_ASSETS_API;
+export const HOST_API_URL = process.env.NEXT_PUBLIC_HOST_API_URL;
+export const WEB_SOCKET_URL = process.env.NEXT_PUBLIC_WEB_SOCKET_URL;
 export const GATEWAY_API_URL = process.env.NEXT_PUBLIC_MYDRESSIN_GATEWAY_API_URL ;
 
 
diff --git a/src/hooks/use-async.ts b/src/hooks/use-async.ts
new file mode 100644
index 00000000..c30e75b4
--- /dev/null
+++ b/src/hooks/use-async.ts
@@ -0,0 +1,27 @@
+//@hook/use-async
+
+import { useState, useCallback } from 'react';
+
+type AsyncFunction = (...args: any[]) => Promise<void>;
+
+const useAsync = (asyncFunction: AsyncFunction) => {
+  const [loading, setLoading] = useState<boolean>(false);
+
+  const execute = useCallback(
+    async (...args: any[]) => {
+      setLoading(true);
+      try {
+        await asyncFunction(...args);
+      } catch (error) {
+        console.error('Error executing async function:', error);
+      } finally {
+        setLoading(false);
+      }
+    },
+    [asyncFunction]
+  );
+
+  return { loading, execute };
+};
+
+export default useAsync;
diff --git a/src/hooks/use-live-comments.ts b/src/hooks/use-live-comments.ts
index d6740040..64577430 100644
--- a/src/hooks/use-live-comments.ts
+++ b/src/hooks/use-live-comments.ts
@@ -7,13 +7,14 @@ import { ILive, ILiveComment } from "@/shared/types/live";
 import { useGetCommentsLive } from "@/shared/api/live";
 import { mutate } from "swr";
 import { endpoints } from "@/shared/api/server";
+import { WEB_SOCKET_URL } from "@/config-global";
 
 type LiveCommentsContextType = {
     comments: ILiveComment[];
     pinnedComments: ILiveComment[];
 };
 
-const WEB_SOCKET_URL = process.env.WEB_SOCKET_URL || "http://15.237.175.171:8080/ws";
+;
 
 const useLiveComments = ({ id, status }: ILive): LiveCommentsContextType => {
     const [comments, setComments] = useState<ILiveComment[]>([]);
@@ -75,7 +76,7 @@ const useLiveComments = ({ id, status }: ILive): LiveCommentsContextType => {
 
     useEffect(() => {
         if (!clientRef.current) {
-            socketRef.current = new SockJS(WEB_SOCKET_URL);
+            socketRef.current = new SockJS(WEB_SOCKET_URL as string);
             clientRef.current = Stomp.over(socketRef.current);
 
             clientRef.current.connect({}, () => {
diff --git a/src/shared/api/live.ts b/src/shared/api/live.ts
index dd6f81da..dadc2904 100644
--- a/src/shared/api/live.ts
+++ b/src/shared/api/live.ts
@@ -1,8 +1,9 @@
-import { AllLivesAnalytics, ILive, ILiveComment, ILiveItem, ILiveProduct, ILiveStatistic, ILiveStatisticsSummary, LiveProductStatus, LiveStatus } from "@/shared/types/live";
+import { AllLivesAnalytics, ILive, ILiveComment, ILiveItem, ILiveProduct, ILiveStatistic, ILiveStatisticsSummary, LiveProductStatus, LiveStatus, TimeStampProduct } from "@/shared/types/live";
 import { generateStatisticsForLives } from "../_mock";
 import useSWR, { mutate } from 'swr';
 import { useMemo } from 'react';
 import axiosInstance, { fetcher, endpoints } from './server';
+import { update } from "lodash";
 
 const options = {
     revalidateIfStale: false,
@@ -40,16 +41,16 @@ function sortLivesByStatus(lives: ILiveItem[]): ILiveItem[] {
 export async function addLive(data: Record<string, any>, image: File) {
     const formData = new FormData();
     formData.append('image', image);
-    formData.append('data',new Blob([JSON.stringify(data)], { type: 'application/json' })); // Serialize the data object
+    formData.append('data', new Blob([JSON.stringify(data)], { type: 'application/json' }));
 
-    const response = await axiosInstance.post('/live', formData, {
+    const response = await axiosInstance.post(endpoints.live.create, formData, {
         headers: {
             'Content-Type': 'multipart/form-data'
         }
     });
 
     const newData = response.data;
-    mutate([endpoints.live.stream], (lives: ILiveItem[] = []) => [newData, ...lives], false);
+    mutate([endpoints.live.all], (lives: ILiveItem[] = []) => [newData, ...lives], false);
     return newData;
 }
 
@@ -60,16 +61,16 @@ export async function editLive(liveId: string, data: Record<string, any>, image?
         if (image) {
             formData.append('image', image);
         }
-        formData.append('data', new Blob([JSON.stringify(data)], { type: 'application/json' })); 
+        formData.append('data', new Blob([JSON.stringify(data)], { type: 'application/json' }));
 
-        const response = await axiosInstance.put(`${endpoints.live.stream}/${liveId}`, formData, {
+        const response = await axiosInstance.put(endpoints.live.update(liveId), formData, {
             headers: {
                 'Content-Type': 'multipart/form-data'
             }
         });
 
         const newData = response.data;
-        mutate([endpoints.live.stream], (lives: ILiveItem[] = []) => {
+        mutate([endpoints.live.all], (lives: ILiveItem[] = []) => {
             const index = lives.findIndex((live) => live.id === liveId);
             if (index > -1) {
                 lives[index] = { ...lives[index], ...newData };
@@ -78,7 +79,7 @@ export async function editLive(liveId: string, data: Record<string, any>, image?
         }, false);
 
         mutate(
-            [`${endpoints.live.stream}/${liveId}`],
+            [endpoints.live.get(liveId)],
             (live: ILive | null = null) => {
                 if (live) {
                     live = { ...live, ...newData };
@@ -95,11 +96,14 @@ export async function editLive(liveId: string, data: Record<string, any>, image?
     }
 }
 
+
+
+
 export async function deleteLive(liveId: string) {
-    await axiosInstance.delete(`${endpoints.live.stream}/${liveId}`);
+    await axiosInstance.delete(endpoints.live.delete(liveId));
 
     mutate(
-        [endpoints.live.stream],
+        [endpoints.live.all],
         (lives: ILiveItem[] = []) => {
             const index = lives.findIndex((live) => live.id === liveId);
             if (index > -1) {
@@ -111,9 +115,10 @@ export async function deleteLive(liveId: string) {
     );
 }
 
+
 export async function archiveLive(liveId: string) {
-    await axiosInstance.post(`${endpoints.live.stream}/${liveId}/archive`);
-    mutate([endpoints.live.stream], (lives: ILiveItem[] = []) => {
+    await axiosInstance.post(endpoints.live.archive(liveId));
+    mutate([endpoints.live.all], (lives: ILiveItem[] = []) => {
         const index = lives.findIndex((live) => live.id === liveId);
         if (index > -1) {
             lives[index].status = LiveStatus.ARCHIVED;
@@ -122,21 +127,22 @@ export async function archiveLive(liveId: string) {
     }, true);
 
     mutate(
-        [`${endpoints.live.stream}/${liveId}`],
+        [endpoints.live.get(liveId)],
         (live: ILive | null = null) => {
             if (live) {
                 live.status = LiveStatus.ARCHIVED;
             }
             return live;
         },
-        true
+        false
     );
 }
 
 
+
 export async function restoreLive(liveId: string) {
-    await axiosInstance.post(`${endpoints.live.stream}/${liveId}/restore`);
-    mutate([endpoints.live.stream], (lives: ILiveItem[] = []) => {
+    await axiosInstance.post(endpoints.live.restore(liveId));
+    mutate([endpoints.live.all], (lives: ILiveItem[] = []) => {
         const index = lives.findIndex((live) => live.id === liveId);
         if (index > -1) {
             lives[index].status = LiveStatus.REVIEW;
@@ -145,23 +151,23 @@ export async function restoreLive(liveId: string) {
     }, true);
 
     mutate(
-        [`${endpoints.live.stream}/${liveId}`],
+        [endpoints.live.get(liveId)],
         (live: ILive | null = null) => {
             if (live) {
                 live.status = LiveStatus.REVIEW;
             }
             return live;
         },
-        true
+        false
     );
 }
 
 
+
 export async function publishLive(liveId: string) {
-    const URL = `${endpoints.live.stream}/${liveId}/publish`;
-    await axiosInstance.post(URL);
+    await axiosInstance.post(endpoints.live.publish(liveId));
     mutate(
-        [`${endpoints.live.stream}/${liveId}`],
+        [endpoints.live.get(liveId)],
         (live: ILive | null = null) => {
             if (live) {
                 live.status = LiveStatus.REPLAY;
@@ -172,7 +178,7 @@ export async function publishLive(liveId: string) {
     );
 
     mutate(
-        [endpoints.live.stream],
+        [endpoints.live.all],
         (lives: ILiveItem[] = []) => {
             const index = lives.findIndex((live) => live.id === liveId);
             if (index > -1) {
@@ -186,7 +192,7 @@ export async function publishLive(liveId: string) {
 
 
 export function useGetLives() {
-    const URL = [endpoints.live.stream];
+    const URL = [endpoints.live.all];
 
     const { data, isLoading, error, isValidating } = useSWR<ILiveItem[]>(URL, fetcher, options);
 
@@ -202,26 +208,29 @@ export function useGetLives() {
 }
 
 export function useGetLive(liveId: string) {
-    const URL = [`${endpoints.live.stream}/${liveId}`];
+    const URL = [endpoints.live.get(liveId)];
     const { data, isLoading, error } = useSWR(URL, fetcher, options);
     return { liveData: data as ILive, liveIsLoading: isLoading, liveError: error };
 }
 
+
 /////////////////////////////////Live Statistics API//////////////////////////////
 //////////////////////////////////////////////////////////////////////////////////
 
 export async function getRealTimeStats(id: string): Promise<ILiveStatistic> {
-    const response = await axiosInstance.get<ILiveStatistic>(endpoints.live.stats.realTime(id));
+    const response = await axiosInstance.get<ILiveStatistic>(endpoints.stats.getStreamStats(id));
     return response.data;
 }
 
+
 export async function getLiveStatistics(liveId: string) {
-    const response = await axiosInstance.get<ILiveStatisticsSummary>(endpoints.live.stats.summary(liveId));
+    const response = await axiosInstance.get<ILiveStatisticsSummary>(endpoints.stats.getStreamSummary(liveId));
     return response.data;
 }
 
+
 export async function getLiveStatisticsForAllLives() {
-    const response = await axiosInstance.get<AllLivesAnalytics>(endpoints.live.stats.summaryAll);
+    const response = await axiosInstance.get<AllLivesAnalytics>(endpoints.stats.getAllLivesSummary);
     return response.data;
 }
 
@@ -260,68 +269,53 @@ export function useGetCommentsLive(liveId: string) {
     );
 }
 
-export async function deleteCommentLive(commentId: string | undefined, liveId: string | undefined) {
+
+export async function deleteCommentLive(commentId: string, liveId: string) {
     await axiosInstance.delete(endpoints.comments.delete(commentId, liveId));
 }
 
-export async function pinCommentLive(commentId: string | undefined, liveId: string | undefined) {
+export async function pinCommentLive(commentId: string, liveId: string) {
     await axiosInstance.post(endpoints.comments.pin(commentId, liveId));
 }
 
-export async function unpinCommentLive(commentId: string | undefined, liveId: string | undefined) {
+
+export async function unpinCommentLive(commentId: string, liveId: string) {
     await axiosInstance.post(endpoints.comments.unpin(commentId, liveId));
 }
 
+
 /////////////////////////////////Live Product API////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////////
 
-export async function addProductLive(liveId: string, productId: string, startTime: number, endTime: number) {
-    await axiosInstance.post(`${endpoints.live.products}/${productId}/stream/${liveId}`, { startTime, endTime });
-
-    mutate(
-        [`${endpoints.live.stream}/${liveId}/products`],
-        (products: ILiveProduct[] = []) => {
-            const index = products.findIndex((product) => product.id === productId);
-            if (index > -1) {addLive
-                products[index] = { ...products[index], startTime, endTime, status: LiveProductStatus.PRESENTED };
-            }
-            return [...products];
-        },
-        false
-    );
-}
 
 
 export async function searchProductLive(sku: string) {
-    return await axiosInstance.get(`${endpoints.product}/${sku}`);
+    return await axiosInstance.get(endpoints.product.search(sku));
 }
 
 export async function addProductToLive(liveId: string, productId: string) {
-    const response = await axiosInstance.post<ILiveProduct>(`${endpoints.live.products}/add`, null, {
-        params: { liveId, productId }
-    });
+    const response = await axiosInstance.post<ILiveProduct>(endpoints.liveProducts.add(productId, liveId));
 
-    mutate([`${endpoints.live.stream}/${liveId}/products`], (products: ILiveProduct[] = []) => {
-        products.push(response.data);
+    mutate([endpoints.liveProducts.all(liveId)], (products: ILiveProduct[] = []) => {
+        products.push({...response.data, timeStampProduct: []});
         return [...products];
-    }, false
-    );
+    }, false);
 }
 
 
 
 export function useGetProducts() {
-    const URL = [`${endpoints.product}?size=100&page=1`];
+    const URL = [endpoints.product.all(1, 100)];
     const { data, isLoading } = useSWR(URL, fetcher, options);
     return { productsData: data as ILiveProduct[], productsLoading: isLoading };
 }
 
-export async function deleteProductLive(productId: string, liveId: string) {
-    await axiosInstance.delete(`${endpoints.live.products}/${productId}/stream/${liveId}`);
+export async function deleteProductLive(liveProductId: string, liveId: string) {
+    await axiosInstance.delete(endpoints.liveProducts.delete(liveId, liveProductId));
     mutate(
-        [`${endpoints.live.stream}/${liveId}/products`],
+        [endpoints.liveProducts.all(liveId)],
         (products: ILiveProduct[] = []) => {
-            const index = products.findIndex((product) => product.id === productId);
+            const index = products.findIndex((product) => product.id == liveProductId);
             if (index > -1) {
                 products.splice(index, 1);
             }
@@ -330,9 +324,8 @@ export async function deleteProductLive(productId: string, liveId: string) {
         false
     );
 }
-
 export function getProductsLive(liveId: string) {
-    const URL = [`${endpoints.live.stream}/${liveId}/products`];
+    const URL = [endpoints.liveProducts.all(liveId)];
     const { data, isLoading, error, isValidating } = useSWR<ILiveProduct[]>(URL, fetcher, options);
 
     return useMemo(
@@ -346,17 +339,66 @@ export function getProductsLive(liveId: string) {
     );
 }
 
+
+export async function addTimeStampProduct(liveId: string, productId: string, startTime: number, endTime: number) {
+    const response = await axiosInstance.post<TimeStampProduct>(endpoints.liveProducts.addTimeStamp(productId, startTime, endTime));
+
+    mutate(
+        [endpoints.liveProducts.all(liveId)],
+        (products: ILiveProduct[] = []) => {
+            const index = products.findIndex((product) => product.id === productId);
+            if (index > -1) {
+                products[index] = { ...products[index], timeStampProduct: [...products[index].timeStampProduct, response.data] };
+            }
+            return [...products];
+        },
+        false
+    );
+}
+
+export async function deleteTimeStampProduct(id: string) {
+    await axiosInstance.delete(endpoints.liveProducts.deleteTimeStamp(id));
+    mutate(
+        [endpoints.liveProducts.all(id)],
+        (products: ILiveProduct[] = []) => {
+            const productIndex = products.findIndex((product) => product.id == id);
+            if (productIndex > -1) {
+                products[productIndex].timeStampProduct = products[productIndex].timeStampProduct.filter((timeStamp) => timeStamp.id != id);
+                console.log('products[productIndex].timeStampProduct', products[productIndex].timeStampProduct);
+            }
+            return [...products];
+        },
+        true
+    );
+}
+
+
+
+export async function presentProductLive(productId: string, liveId: string, startTime: number) {
+    await axiosInstance.post(endpoints.liveProducts.present(liveId, productId, startTime));
+    mutate(
+        [endpoints.liveProducts.all(liveId)],
+        (products: ILiveProduct[] = []) => {
+            const index = products.findIndex((product) => product.id === productId);
+            if (index > -1) {
+                products[index].status = LiveProductStatus.IN_PRESENTATION;
+            }
+            return [...products];
+        },
+        false
+    );
+}
+
+
 export async function pushProductLive(productId: string, liveId: string, startTime: number) {
-    await axiosInstance.post(`${endpoints.live.products}/push`, null, {
-        params: { productId, liveId, startTime }
-    });
+    const response = await axiosInstance.post<TimeStampProduct>(endpoints.liveProducts.push(productId, startTime));
 
     mutate(
-        [`${endpoints.live.stream}/${liveId}/products`],
+        [endpoints.liveProducts.all(liveId)],
         (products: ILiveProduct[] = []) => {
             const index = products.findIndex((product) => product.id === productId);
             if (index > -1) {
-                products[index] = { ...products[index], startTime, status: LiveProductStatus.IN_PRESENTATION };
+                products[index] = { ...products[index], timeStampProduct: [...products[index].timeStampProduct, response.data], status: LiveProductStatus.IN_PRESENTATION };
             }
             return [...products];
         },
@@ -366,32 +408,58 @@ export async function pushProductLive(productId: string, liveId: string, startTi
 
 export async function hideProductLive(productId: string, liveId: string, endTime: number) {
     try {
-        await axiosInstance.post(`${endpoints.live.products}/hide`, null, {
-            params: { productId, liveId, endTime }
-        });
+        const response = await axiosInstance.post<TimeStampProduct>(endpoints.liveProducts.hide(productId, endTime));
 
         mutate(
-            [`${endpoints.live.stream}/${liveId}/products`],
+            [endpoints.liveProducts.all(liveId)],
             (products: ILiveProduct[] = []) => {
-                const index = products.findIndex((product) => product.id === productId);
-                if (index > -1) {
-                    products[index] = { ...products[index], endTime, status: LiveProductStatus.PRESENTED };
+                const productIndex = products.findIndex((product) => product.id === productId);
+                if (productIndex > -1) {
+                    products[productIndex].status = LiveProductStatus.PRESENTED
+                    const timeStampIndex = products[productIndex].timeStampProduct.findIndex((timeStamp) => timeStamp.id === response.data.id);
+                    if (timeStampIndex > -1) {
+                        products[productIndex].timeStampProduct[timeStampIndex] = response.data;
+                    } else {
+                        products[productIndex].timeStampProduct.push(response.data);
+                    }
+
                 }
                 return [...products];
             },
             false
         );
     } catch (e) {
+        console.error('Error hiding product:', e);
     }
 }
+
+
+export async function updateTimeStampProduct(id: string, startTime: number, endTime: number) {
+    const response = await axiosInstance.put<TimeStampProduct>(endpoints.liveProducts.updateTimeStamp(id, startTime, endTime));
+    mutate(
+        [endpoints.liveProducts.all(id)],
+        (products: ILiveProduct[] = []) => {
+            const productIndex = products.findIndex((product) => product.id === id);
+            if (productIndex > -1) {
+                const timeStampIndex = products[productIndex].timeStampProduct.findIndex((timeStamp) => timeStamp.id === response.data.id);
+                if (timeStampIndex > -1) {
+                    products[productIndex].timeStampProduct[timeStampIndex] = response.data;
+                } else {
+                    products[productIndex].timeStampProduct.push(response.data);
+                }
+            }
+            return [...products];
+        },
+        false
+    );
+}
 /////////////////////////////////Live State API////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
 
 export async function stopLive(liveId: string) {
-    const URL = `${endpoints.live.stream}/${liveId}/stop`;
-    await axiosInstance.post(URL);
+    await axiosInstance.post(endpoints.live.stop(liveId));
     mutate(
-        [`${endpoints.live.stream}/${liveId}`],
+        [endpoints.live.get(liveId)],
         (live: ILive | null = null) => {
             if (live) {
                 live.status = LiveStatus.REVIEW;
@@ -402,7 +470,7 @@ export async function stopLive(liveId: string) {
     );
 
     mutate(
-        [endpoints.live.stream],
+        [endpoints.live.all],
         (lives: ILiveItem[] = []) => {
             const index = lives.findIndex((live) => live.id === liveId);
             if (index > -1) {
@@ -415,10 +483,9 @@ export async function stopLive(liveId: string) {
 }
 
 export async function startLive(liveId: string) {
-    const URL = `${endpoints.live.stream}/${liveId}/start`;
-    await axiosInstance.post(URL);
+    await axiosInstance.post(endpoints.live.start(liveId));
     mutate(
-        [`${endpoints.live.stream}/${liveId}`],
+        [endpoints.live.get(liveId)],
         (live: ILive | null = null) => {
             if (live) {
                 live.status = LiveStatus.ONGOING;
@@ -430,7 +497,7 @@ export async function startLive(liveId: string) {
     );
 
     mutate(
-        [endpoints.live.stream],
+        [endpoints.live.all],
         (lives: ILiveItem[] = []) => {
             const index = lives.findIndex((live) => live.id === liveId);
             if (index > -1) {
@@ -440,8 +507,4 @@ export async function startLive(liveId: string) {
         },
         false
     );
-}
-
-
-
-
+}
\ No newline at end of file
diff --git a/src/shared/api/server.ts b/src/shared/api/server.ts
index 61ecc60a..20918f8e 100644
--- a/src/shared/api/server.ts
+++ b/src/shared/api/server.ts
@@ -1,10 +1,13 @@
+import { HOST_API_URL } from '@/config-global';
 import axios, { AxiosRequestConfig } from 'axios';
 import { comment } from 'postcss';
 
 import { shippingClassesList } from '../_mock/_shipping';
+import { HOST_API } from '@/config-global';
+
+
 
 
-export const HOST_API = 'http://15.237.175.171:8080';
 
 
 
@@ -30,22 +33,51 @@ export const fetcher = async (args: string | [string, AxiosRequestConfig]) => {
 export const endpoints = {
   comments: {
     add: "/chat/message",
-    get: (liveId: string) => `/chat/stream/${liveId}`,
-    delete: (commentId: string | undefined, liveId: string | undefined) => `/chat/stream/${liveId}/message/${commentId}`,
-    pin: (commentId: string | undefined, liveId: string | undefined) => `/chat/stream/${liveId}/pin/${commentId}`,
-    unpin: (commentId: string | undefined, liveId: string | undefined) => `/chat/stream/${liveId}/unpin/${commentId}`,
+    get: (liveId: string) => `/chat/live?streamId=${liveId}`,
+    delete: (commentId: string, liveId: string) => `/chat/live/delete?streamId=${liveId}&messageId=${commentId}`,
+    pin: (commentId: string, liveId: string) => `/chat/live/pin?streamId=${liveId}&messageId=${commentId}`,
+    unpin: (commentId: string, liveId: string) => `/chat/live/unpin?streamId=${liveId}&messageId=${commentId}`,
+  },
+  product: {
+    all: (page: number, size: number) => `/products/all?page=${page}&size=${size}`,
+    search: (sku: string) => `/products/search?sku=${sku}`,
   },
-  product: "/products",
   live: {
-    stream: '/live',
-    products : '/live-product',
-    stats : {
-      summaryAll : '/api/stats/summary',
-      summary : (liveId:string) => `/api/stats/${liveId}/summary`,
-      realTime : (keyStream:string) => `/api/stats/${keyStream}`,
-    }
+    all: '/live/all',
+    client: '/live/client',
+    get: (liveId: string) => `/live?liveId=${liveId}`,
+    create: '/live/create',
+    update: (liveId: string) => `/live/update?liveId=${liveId}`,
+    start: (liveId: string) => `/live/start?liveId=${liveId}`,
+    stop: (liveId: string) => `/live/stop?liveId=${liveId}`,
+    publish: (liveId: string) => `/live/publish?liveId=${liveId}`,
+    delete: (liveId: string) => `/live/delete?liveId=${liveId}`,
+    archive: (liveId: string) => `/live/archive?liveId=${liveId}`,
+    restore: (liveId: string) => `/live/restore?liveId=${liveId}`,
+    ongoing: '/live/ongoing'
   },
-
+  cards: {
+    add: (userId: string, productId: string) => `/cards/add?userId=${userId}&productId=${productId}`,
+    all: (userId: string) => `/cards/all?userId=${userId}`
+  },
+  liveProducts: {
+    presented: (liveId: string) => `/live-products/presented?liveId=${liveId}`,
+    all: (liveId: string) => `/live-products/all?liveId=${liveId}`,
+    add: (liveProductId: string, liveId: string) => `/live-products/add?liveProductId=${liveProductId}&liveId=${liveId}`,
+    delete: (liveId: string, liveProductId:string) => `/live-products/delete?liveId=${liveId}&liveProductId=${liveProductId}`,
+    present: (liveId: string, liveProductId: string, startTime: number) => `/live-products/present?liveId=${liveId}&liveProductId=${liveProductId}&startTime=${startTime}`,
+    push: (liveProductId: string, startTime: number) => `/live-products/push?liveProductId=${liveProductId}&startTime=${startTime}`,
+    hide: (liveProductId: string, endTime: number) => `/live-products/hide?liveProductId=${liveProductId}&endTime=${endTime}`,
+    addTimeStamp: (liveProductId: string, startTime: number, endTime: number) => `/live-products/add-time-stamp?liveProductId=${liveProductId}&startTime=${startTime}&endTime=${endTime}`,
+    deleteTimeStamp: (id: string) => `/live-products/delete-time-stamp?id=${id}`,
+    updateTimeStamp: (id: string, startTime: number, endTime: number) => `/live-products/update-time-stamp?id=${id}&startTime=${startTime}&endTime=${endTime}`
+  },
+  stats: {
+    getStats:`/api/stats`,
+    getStreamStats: (liveId: string) => `/api/stats?liveId=${liveId}`,
+    getStreamSummary: (liveId: string) => `/api/stats/summary?liveId=${liveId}`,
+    getAllLivesSummary: `/api/stats/summary/all`,
+  },,
   shipping:{
     shippingClass:{
       getAll: `/shipping/shipping-class`,
@@ -135,3 +167,4 @@ export const endpoints = {
   
 
 };
+
diff --git a/src/shared/layouts/common/notifications-popover/notification-item.tsx b/src/shared/layouts/common/notifications-popover/notification-item.tsx
index ec055419..d86fbc00 100644
--- a/src/shared/layouts/common/notifications-popover/notification-item.tsx
+++ b/src/shared/layouts/common/notifications-popover/notification-item.tsx
@@ -145,7 +145,7 @@ export default function NotificationItem({ notification }: NotificationItemProps
       }}
     >
       <FileThumbnail
-        file="http://15.237.175.171:8080/httpsdesign-suriname-2015.mp3"
+        file="http://localhost:8080/httpsdesign-suriname-2015.mp3"
         sx={{ width: 40, height: 40 }}
       />
 
diff --git a/src/shared/sections/lives/add-edit-live/add-live-view.tsx b/src/shared/sections/lives/add-edit-live/add-live-view.tsx
index 02cc7c3c..d0f1a23b 100644
--- a/src/shared/sections/lives/add-edit-live/add-live-view.tsx
+++ b/src/shared/sections/lives/add-edit-live/add-live-view.tsx
@@ -1,3 +1,4 @@
+
 "use client";
 
 import * as Yup from 'yup';
@@ -30,14 +31,14 @@ import { ILiveProduct } from '@/shared/types/live';
 import { addLive } from '@/shared/api/live';
 import { useRouter } from 'next/navigation';
 import ImageCrop from '@/components/image-crop';
+import useAsync from '@/hooks/use-async';
 
 export default function AddLiveView() {
     const mdUp = useResponsive('up', 'md');
     const { enqueueSnackbar } = useSnackbar();
     const settings = useSettingsContext();
     const router = useRouter();
-    const [addLoading, setAddLoading] = useState(false);
-
+    
     const NewLiveSchema = Yup.object().shape({
         title: Yup.string().required('Title is required'),
         chatName: Yup.string().required('Moderator is required'),
@@ -91,28 +92,29 @@ export default function AddLiveView() {
         setProducts(products.filter((p) => p.id !== product.id));
     };
 
+    const asyncAddLive = useAsync(async (formData, image) => {
+        await addLive(formData, image);
+    });
+
     const onSubmit = handleSubmit((data) => {
-        if(addLoading) return;
-        setAddLoading(true);
-        const formData = { ...data, products: products.map((product) => product.id) }
-        if (image) addLive(formData, image)
-            .then(() => {
-                enqueueSnackbar('live crée avec succés', { variant: 'success' });
-                reset();
-                setProducts([]);
-                setImage(null);
-                router.push(paths.dashboard.live.root)
-                setAddLoading(false);
-                
-            })
-            .catch((err) => {
-                enqueueSnackbar(err.message, { variant: 'error' });
-                console.error(err);
-                setAddLoading(false);
-            })
-        else  enqueueSnackbar('Veuillez ajouter une image de couverture', { variant: 'error' });
-            
-            
+        if (asyncAddLive.loading) return;
+        const formData = { ...data, products: products.map((product) => product.id) };
+        if (image) {
+            asyncAddLive.execute(formData, image)
+                .then(() => {
+                    enqueueSnackbar('Live créé avec succès', { variant: 'success' });
+                    reset();
+                    setProducts([]);
+                    setImage(null);
+                    router.push(paths.dashboard.live.root);
+                })
+                .catch((err) => {
+                    enqueueSnackbar(err.message, { variant: 'error' });
+                    console.error(err);
+                });
+        } else {
+            enqueueSnackbar('Veuillez ajouter une image de couverture', { variant: 'error' });
+        }
     });
 
     const renderDetails = (
@@ -338,8 +340,8 @@ export default function AddLiveView() {
                     type="submit"
                     variant="contained"
                     size="large"
-                    loading={addLoading}
-                    disabled={addLoading}
+                    loading={asyncAddLive.loading}
+                    disabled={asyncAddLive.loading}
                     sx={{ ml: 2 }}
                 >
                     Enregistrer
diff --git a/src/shared/sections/lives/all-lives/live-table-row.tsx b/src/shared/sections/lives/all-lives/live-table-row.tsx
index 3aa9bc08..2ed9c4b5 100644
--- a/src/shared/sections/lives/all-lives/live-table-row.tsx
+++ b/src/shared/sections/lives/all-lives/live-table-row.tsx
@@ -1,10 +1,6 @@
-
-import Button from '@mui/material/Button';
 import Avatar from '@mui/material/Avatar';
-import Divider from '@mui/material/Divider';
 import MenuItem from '@mui/material/MenuItem';
 import TableRow from '@mui/material/TableRow';
-import Checkbox from '@mui/material/Checkbox';
 import TableCell from '@mui/material/TableCell';
 import IconButton from '@mui/material/IconButton';
 import ListItemText from '@mui/material/ListItemText';
@@ -20,8 +16,7 @@ import CustomPopover, { usePopover } from '@/shared/components/custom-popover';
 import { ILiveItem, LiveStatus } from '@/shared/types/live';
 import { archiveLive, deleteLive, publishLive, restoreLive } from '@/shared/api/live';
 import LoadingButton from '@mui/lab/LoadingButton';
-import { useState } from 'react';
-
+import useAsync from '@/hooks/use-async';
 
 type Props = {
   row: ILiveItem;
@@ -29,7 +24,7 @@ type Props = {
   onViewRow: VoidFunction;
   onDetails: VoidFunction;
   onEditRow: VoidFunction;
-  onViewStats: VoidFunction
+  onViewStats: VoidFunction;
 };
 
 export default function LiveTableRow({
@@ -43,72 +38,74 @@ export default function LiveTableRow({
   const popover = usePopover();
   const openDetails = useBoolean();
   const deleteConfirm = useBoolean();
-  const publishConirm = useBoolean();
-  const archiveConirm = useBoolean();
-  const restoreConirm = useBoolean();
-  const [loading, setLoading] = useState(false);
+  const publishConfirm = useBoolean();
+  const archiveConfirm = useBoolean();
+  const restoreConfirm = useBoolean();
   const { enqueueSnackbar } = useSnackbar();
 
-  const handleDelete = async () => {
-    try {
-      setLoading(true);
-      await deleteLive(row.id);
-      deleteConfirm.onFalse();
-      enqueueSnackbar('live supprimé avec succés', { variant: 'success' });
-    } catch (error) {
-      enqueueSnackbar('erreur lors de la supression', { variant: 'error' });
-    } finally {
-      setLoading(false);
-    }
-  }
-
-  const handlePublish = async () => {
-    try {
-      setLoading(true);
-      await publishLive(row.id);
-      publishConirm.onFalse();
-      enqueueSnackbar('live publié avec succés', { variant: 'success' });
-    } catch (error) {
-      enqueueSnackbar("erreur lors de la publication", { variant: 'error' });
-    } finally {
-      setLoading(false);
-    }
-  }
-
-  const handleArchive = async () => {
-    try {
-      setLoading(true);
-      await archiveLive(row.id);
-      archiveConirm.onFalse();
-      enqueueSnackbar('live archivé avec succés', { variant: 'success' });
-    } catch (error) {
-      enqueueSnackbar("erreur lors de l'archivation", { variant: 'error' });
-    } finally {
-      setLoading(false);
-    }
-  }
-
-  const handleUnarchive = async () => {
-    try {
-      setLoading(true);
-      await restoreLive(row.id);
-      restoreConirm.onFalse();
-      enqueueSnackbar('live désarchivé avec succés', { variant: 'success' });
-    } catch (error) {
-      enqueueSnackbar("erreur lors de la désarchivation", { variant: 'error' });
-    } finally {
-      setLoading(false);
-    }
-  }
-
-
-
+  const asyncDeleteLive = useAsync(async () => {
+    await deleteLive(row.id);
+  });
+
+  const asyncPublishLive = useAsync(async () => {
+    await publishLive(row.id);
+  });
+
+  const asyncArchiveLive = useAsync(async () => {
+    await archiveLive(row.id);
+  });
+
+  const asyncRestoreLive = useAsync(async () => {
+    await restoreLive(row.id);
+  });
+
+  const handleDelete = () => {
+    asyncDeleteLive.execute()
+      .then(() => {
+        deleteConfirm.onFalse();
+        enqueueSnackbar('live supprimé avec succès', { variant: 'success' });
+      })
+      .catch(() => {
+        enqueueSnackbar('erreur lors de la suppression', { variant: 'error' });
+      });
+  };
+
+  const handlePublish = () => {
+    asyncPublishLive.execute()
+      .then(() => {
+        publishConfirm.onFalse();
+        enqueueSnackbar('live publié avec succès', { variant: 'success' });
+      })
+      .catch(() => {
+        enqueueSnackbar('erreur lors de la publication', { variant: 'error' });
+      });
+  };
+
+  const handleArchive = () => {
+    asyncArchiveLive.execute()
+      .then(() => {
+        archiveConfirm.onFalse();
+        enqueueSnackbar('live archivé avec succès', { variant: 'success' });
+      })
+      .catch(() => {
+        enqueueSnackbar('erreur lors de l\'archivation', { variant: 'error' });
+      });
+  };
+
+  const handleUnarchive = () => {
+    asyncRestoreLive.execute()
+      .then(() => {
+        restoreConfirm.onFalse();
+        enqueueSnackbar('live désarchivé avec succès', { variant: 'success' });
+      })
+      .catch(() => {
+        enqueueSnackbar('erreur lors de la désarchivation', { variant: 'error' });
+      });
+  };
 
   return (
     <>
-
-      <TableRow hover  >
-
+      <TableRow hover>
         <TableCell sx={{ cursor: 'pointer' }} onClick={onDetails}>
           <Avatar
             alt={title}
@@ -118,7 +115,7 @@ export default function LiveTableRow({
           />
         </TableCell>
 
-        <TableCell sx={{ cursor: 'pointer' }} onClick={onDetails} >
+        <TableCell sx={{ cursor: 'pointer' }} onClick={onDetails}>
           {title}
         </TableCell>
 
@@ -146,7 +143,7 @@ export default function LiveTableRow({
           />
         </TableCell>
 
-        <TableCell sx={{ cursor: 'pointer' }} onClick={onDetails} >{description}</TableCell>
+        <TableCell sx={{ cursor: 'pointer' }} onClick={onDetails}>{description}</TableCell>
         <TableCell sx={{ cursor: 'pointer' }} onClick={onDetails}>
           <Label
             variant="soft"
@@ -173,7 +170,6 @@ export default function LiveTableRow({
             <Iconify icon="eva:more-vertical-fill" />
           </IconButton>
         </TableCell>
-
       </TableRow>
 
       <CustomPopover
@@ -185,38 +181,35 @@ export default function LiveTableRow({
         <MenuItem
           onClick={() => {
             onViewRow();
-            openDetails.onTrue()
+            openDetails.onTrue();
             popover.onClose();
-
           }}
-
         >
-
           <Iconify icon="solar:eye-bold" />
           voir
         </MenuItem>
         <MenuItem
           onClick={() => {
             onDetails();
-            openDetails.onTrue()
+            openDetails.onTrue();
             popover.onClose();
-
           }}
-
         >
           <Iconify icon="gg:details-more" />
           détails
         </MenuItem>
-        {status === LiveStatus.REVIEW && <MenuItem
-          onClick={() => {
-            popover.onClose();
-            publishConirm.onTrue();
-          }}
-          style={{ outline: 'none', color: 'blue' }}
-        >
-          <Iconify icon="ic:baseline-publish" />
-          publier
-        </MenuItem>}
+        {status === LiveStatus.REVIEW && (
+          <MenuItem
+            onClick={() => {
+              popover.onClose();
+              publishConfirm.onTrue();
+            }}
+            style={{ outline: 'none', color: 'blue' }}
+          >
+            <Iconify icon="ic:baseline-publish" />
+            publier
+          </MenuItem>
+        )}
         <MenuItem
           onClick={() => {
             onEditRow();
@@ -224,20 +217,21 @@ export default function LiveTableRow({
           }}
           style={{ outline: 'none' }}
         >
-
           <Iconify icon="solar:pen-bold" />
           Modifier
         </MenuItem>
-        {row.status != LiveStatus.COMING && <MenuItem
-          onClick={() => {
-            onViewStats();
-            popover.onClose();
-          }}
-          style={{ outline: 'none' }}
-        >
-          <Iconify icon="icomoon-free:stats-bars" />
-          Stats
-        </MenuItem>}
+        {row.status !== LiveStatus.COMING && (
+          <MenuItem
+            onClick={() => {
+              onViewStats();
+              popover.onClose();
+            }}
+            style={{ outline: 'none' }}
+          >
+            <Iconify icon="icomoon-free:stats-bars" />
+            Stats
+          </MenuItem>
+        )}
         <MenuItem
           onClick={() => {
             popover.onClose();
@@ -249,25 +243,31 @@ export default function LiveTableRow({
           Supprimer
         </MenuItem>
 
-        {(status === LiveStatus.REPLAY || status === LiveStatus.REVIEW) && <MenuItem
-          onClick={() => {
-            popover.onClose();
-            archiveConirm.onTrue();
-          }}
-          style={{ outline: 'none', color: 'orange' }}
-        > <Iconify icon="system-uicons:archive" />
-          archiver
-        </MenuItem>}
-
-        {status === LiveStatus.ARCHIVED && <MenuItem
-          onClick={() => {
-            popover.onClose();
-            restoreConirm.onTrue();
-          }}
-          style={{ outline: 'none', color: 'orange' }}
-        > <Iconify icon="system-uicons:archive" />
-          restorer
-        </MenuItem>}
+        {(status === LiveStatus.REPLAY || status === LiveStatus.REVIEW) && (
+          <MenuItem
+            onClick={() => {
+              popover.onClose();
+              archiveConfirm.onTrue();
+            }}
+            style={{ outline: 'none', color: 'orange' }}
+          >
+            <Iconify icon="system-uicons:archive" />
+            archiver
+          </MenuItem>
+        )}
+
+        {status === LiveStatus.ARCHIVED && (
+          <MenuItem
+            onClick={() => {
+              popover.onClose();
+              restoreConfirm.onTrue();
+            }}
+            style={{ outline: 'none', color: 'orange' }}
+          >
+            <Iconify icon="system-uicons:archive" />
+            restorer
+          </MenuItem>
+        )}
       </CustomPopover>
       <ConfirmDialog
         open={deleteConfirm.value}
@@ -275,41 +275,41 @@ export default function LiveTableRow({
         title="Supprimer"
         content="Voulez-vous vraiment supprimer ce live?"
         action={
-          <LoadingButton loading={loading} variant="contained" color="error" onClick={handleDelete}>
+          <LoadingButton loading={asyncDeleteLive.loading} variant="contained" color="error" onClick={handleDelete}>
             Supprimer
           </LoadingButton>
         }
       />
       <ConfirmDialog
-        open={publishConirm.value}
-        onClose={publishConirm.onFalse}
+        open={publishConfirm.value}
+        onClose={publishConfirm.onFalse}
         title="publier"
         content="Voulez-vous vraiment publier ce live?"
         action={
-          <LoadingButton loading={loading} variant="contained" color="info" onClick={handlePublish}>
+          <LoadingButton loading={asyncPublishLive.loading} variant="contained" color="info" onClick={handlePublish}>
             publier
           </LoadingButton>
         }
       />
       <ConfirmDialog
-        open={archiveConirm.value}
-        onClose={archiveConirm.onFalse}
+        open={archiveConfirm.value}
+        onClose={archiveConfirm.onFalse}
         title="archiver"
         content="Voulez-vous vraiment archiver ce live?"
         action={
-          <LoadingButton loading={loading} variant="contained" color="warning" onClick={handleArchive}>
+          <LoadingButton loading={asyncArchiveLive.loading} variant="contained" color="warning" onClick={handleArchive}>
             archiver
           </LoadingButton>
         }
       />
 
       <ConfirmDialog
-        open={restoreConirm.value}
-        onClose={restoreConirm.onFalse}
+        open={restoreConfirm.value}
+        onClose={restoreConfirm.onFalse}
         title="restorer"
         content="Voulez-vous vraiment restorer ce live?"
         action={
-          <LoadingButton loading={loading} variant="contained" color="warning" onClick={handleUnarchive}>
+          <LoadingButton loading={asyncRestoreLive.loading} variant="contained" color="warning" onClick={handleUnarchive}>
             restorer
           </LoadingButton>
         }
diff --git a/src/shared/sections/lives/details/view.tsx b/src/shared/sections/lives/details/view.tsx
index e039c975..2fc0f8ca 100644
--- a/src/shared/sections/lives/details/view.tsx
+++ b/src/shared/sections/lives/details/view.tsx
@@ -20,9 +20,9 @@ import { VideoFormatsField } from './video-format';
 import CustomBreadcrumbs from '@/components/custom-breadcrumbs';
 import { paths } from '@/routes/paths';
 import { useSettingsContext } from '@/shared/components/settings';
-import { Avatar, Button, CardMedia, Checkbox, Container, List, ListItem, ListItemAvatar, ListItemText, Paper } from '@mui/material';
+import { Avatar, Button, Container, List, ListItem, ListItemAvatar, ListItemText, Paper } from '@mui/material';
 import { ILiveProduct, LiveStatus } from '@/shared/types/live';
-import { deleteLive, editLive, getProductsLive, publishLive, restoreLive , archiveLive} from '@/shared/api/live';
+import { deleteLive, editLive, getProductsLive, publishLive, restoreLive, archiveLive } from '@/shared/api/live';
 import { useCallback, useEffect, useMemo, useState } from 'react';
 import { useLiveData } from '@/contexts/live-stats';
 import LoadingButton from '@mui/lab/LoadingButton';
@@ -33,6 +33,7 @@ import { styled } from '@mui/material/styles';
 import CopyButton from '@/components/copy-button';
 import { useBoolean } from '@/hooks';
 import { ConfirmDialog } from '@/shared/components/custom-dialog';
+import useAsync from '@/hooks/use-async';
 
 const StyledList = styled(List)({
     overflowY: 'auto',
@@ -56,8 +57,7 @@ const StyledList = styled(List)({
 
 const ProductCard = ({ product }: any) => (
     <Card variant="outlined" key={product.id} sx={{ marginBottom: 2 }}>
-        <ListItem
-        >
+        <ListItem>
             <ListItemAvatar>
                 <Avatar variant="rounded" alt={product.title} sx={{ height: 100, width: 100 }} src={product.image} />
             </ListItemAvatar>
@@ -116,47 +116,73 @@ export default function LiveDetailsView() {
     const archiveConfirm = useBoolean();
     const restoreConfirm = useBoolean();
 
-
-    const handleDelete = async () => {
+    const asyncDeleteLive = useAsync(async () => {
         await deleteLive(liveData.id);
         deleteConfirm.onFalse();
         router.push(paths.dashboard.live.all_lives);
+    });
 
-    }
+    const asyncPublishLive = useAsync(async () => {
+        await publishLive(liveData.id);
+    });
 
-    const handlePublishLive = async () => {
-        try {
-            await publishLive(liveData.id);
-            enqueueSnackbar('Le live a été publié', { variant: 'success' });
-        } catch (err: any) {
-            enqueueSnackbar(err.message as string, { variant: 'error' });
-        } finally {
-            publishConfirm.onFalse();
-        }
-    }
+    const asyncArchiveLive = useAsync(async () => {
+        await archiveLive(liveData.id);
+    });
 
-    const handleArchiveLive = async () => {
-        try {
-            await archiveLive(liveData.id);
-            enqueueSnackbar('Le live a été archivé', { variant: 'success' });
-        } catch (err: any) {
-            enqueueSnackbar(err.message as string, { variant: 'error' });
-        } finally {
-            archiveConfirm.onFalse();
-        }
-    }
+    const asyncRestoreLive = useAsync(async () => {
+        await restoreLive(liveData.id);
+    });
 
+    const handleDelete = () => {
+        asyncDeleteLive.execute()
+            .then(() => {
+                enqueueSnackbar('Live supprimé avec succès', { variant: 'success' });
+            })
+            .catch(() => {
+                enqueueSnackbar('Erreur lors de la suppression', { variant: 'error' });
+            });
+    };
+
+    const handlePublishLive = () => {
+        asyncPublishLive.execute()
+            .then(() => {
+                enqueueSnackbar('Le live a été publié', { variant: 'success' });
+            })
+            .catch((err) => {
+                enqueueSnackbar(err.message, { variant: 'error' });
+            })
+            .finally(() => {
+                publishConfirm.onFalse();
+            });
+    };
+
+    const handleArchiveLive = () => {
+        asyncArchiveLive.execute()
+            .then(() => {
+                enqueueSnackbar('Le live a été archivé', { variant: 'success' });
+            })
+            .catch((err) => {
+                enqueueSnackbar(err.message, { variant: 'error' });
+            })
+            .finally(() => {
+                archiveConfirm.onFalse();
+            });
+    };
+
+    const handleRestoreLive = () => {
+        asyncRestoreLive.execute()
+            .then(() => {
+                enqueueSnackbar('Le live a été restauré', { variant: 'success' });
+            })
+            .catch((err) => {
+                enqueueSnackbar(err.message, { variant: 'error' });
+            })
+            .finally(() => {
+                restoreConfirm.onFalse();
+            });
+    };
 
-    const handleRestoreLive = async () => {
-        try {
-            await restoreLive(liveData.id);
-            enqueueSnackbar('Le live a été restauré', { variant: 'success' });
-        } catch (err: any) {
-            enqueueSnackbar(err.message as string, { variant: 'error' });
-        } finally {
-            restoreConfirm.onFalse();
-        }
-    }
     const methods = useForm({
         resolver: yupResolver(NewLiveSchema),
         defaultValues,
@@ -188,12 +214,14 @@ export default function LiveDetailsView() {
         },
         [router]
     );
+
     const handleViewStats = useCallback(
         (id: string) => {
             router.push(paths.dashboard.live.statistics.single(id));
         },
         [router]
     );
+
     const handleViewInfo = useCallback(
         (id: string) => {
             router.push(paths.dashboard.live.details(id));
@@ -210,7 +238,7 @@ export default function LiveDetailsView() {
         };
         editLive(liveData.id, formData)
             .then(() => {
-                enqueueSnackbar('Live Updated successfully', { variant: 'success' });
+                enqueueSnackbar('Live mis à jour avec succès', { variant: 'success' });
                 setImage(null);
             })
             .catch((err) => {
@@ -514,7 +542,6 @@ export default function LiveDetailsView() {
                     (status == LiveStatus.ONGOING && 'warning') ||
                     (status == LiveStatus.COMING && 'error') ||
                     (status == LiveStatus.REVIEW && 'info') || 'default'
-
                 }
             >
                 {
@@ -553,7 +580,8 @@ export default function LiveDetailsView() {
                         loading={isSubmitting}
                         sx={{ ml: 2 }}
                         onClick={() => handleViewStats(liveData.id)}
-                    ><Iconify sx={{ mr: 2 }} icon="icomoon-free:stats-bars" />
+                    >
+                        <Iconify sx={{ mr: 2 }} icon="icomoon-free:stats-bars" />
                         Statistiques
                     </LoadingButton>
                 )}
@@ -564,7 +592,7 @@ export default function LiveDetailsView() {
                         onClick={publishConfirm.onTrue}
                         sx={{ ml: 2, backgroundColor: 'blue' }}
                     >
-                        <Iconify sx={{ mr: 2 }}  icon="ic:baseline-publish" />
+                        <Iconify sx={{ mr: 2 }} icon="ic:baseline-publish" />
                         Publier
                     </LoadingButton>
                 )}
@@ -574,9 +602,9 @@ export default function LiveDetailsView() {
                         size="large"
                         color='warning'
                         onClick={archiveConfirm.onTrue}
-                        sx={{ ml: 2}}
+                        sx={{ ml: 2 }}
                     >
-                        <Iconify sx={{ mr: 2 }}  icon="dashicons:archive" />
+                        <Iconify sx={{ mr: 2 }} icon="dashicons:archive" />
                         archiver
                     </LoadingButton>
                 )}
@@ -588,7 +616,7 @@ export default function LiveDetailsView() {
                         onClick={restoreConfirm.onTrue}
                         sx={{ ml: 2 }}
                     >
-                        <Iconify  sx={{ mr: 2 }}  icon="mdi:archive-off" />
+                        <Iconify sx={{ mr: 2 }} icon="mdi:archive-off" />
                         restorer
                     </LoadingButton>
                 )}
@@ -606,8 +634,6 @@ export default function LiveDetailsView() {
         </Grid>
     );
 
-
-
     return (
         <Container maxWidth={settings.themeStretch ? false : 'lg'}>
             <CustomBreadcrumbs
@@ -636,9 +662,9 @@ export default function LiveDetailsView() {
                 title="Supprimer"
                 content="Voulez-vous vraiment supprimer ce live?"
                 action={
-                    <Button variant="contained" color="error" onClick={handleDelete}>
+                    <LoadingButton loading={asyncDeleteLive.loading} variant="contained" color="error" onClick={handleDelete}>
                         Supprimer
-                    </Button>
+                    </LoadingButton>
                 }
             />
             <ConfirmDialog
@@ -647,9 +673,9 @@ export default function LiveDetailsView() {
                 title="Publier"
                 content="Voulez-vous publier le live?"
                 action={
-                    <Button variant="contained" color="info" onClick={handlePublishLive}>
+                    <LoadingButton loading={asyncPublishLive.loading} variant="contained" color="info" onClick={handlePublishLive}>
                         Publier
-                    </Button>
+                    </LoadingButton>
                 }
             />
 
@@ -659,9 +685,9 @@ export default function LiveDetailsView() {
                 title="Archiver"
                 content="Voulez-vous archiver le live?"
                 action={
-                    <Button variant="contained" color="warning" onClick={handleArchiveLive}>
+                    <LoadingButton loading={asyncArchiveLive.loading} variant="contained" color="warning" onClick={handleArchiveLive}>
                         Archiver
-                    </Button>
+                    </LoadingButton>
                 }
             />
 
@@ -671,12 +697,11 @@ export default function LiveDetailsView() {
                 title="Restorer"
                 content="Voulez-vous restorer le live?"
                 action={
-                    <Button variant="contained" color="warning" onClick={handleRestoreLive}>
+                    <LoadingButton loading={asyncRestoreLive.loading} variant="contained" color="warning" onClick={handleRestoreLive}>
                         Restorer
-                    </Button>
+                    </LoadingButton>
                 }
-                />
+            />
         </Container>
     );
 }
-
diff --git a/src/shared/sections/lives/supervision/details-comments-input.tsx b/src/shared/sections/lives/supervision/details-comments-input.tsx
index 6deaf53c..cd6babf0 100644
--- a/src/shared/sections/lives/supervision/details-comments-input.tsx
+++ b/src/shared/sections/lives/supervision/details-comments-input.tsx
@@ -85,7 +85,7 @@ export default function CommentsInput({
                         <Typography variant="body1" >
                             {comment?.content}
                         </Typography>
-                        <IconButton onClick={async () => await unpinCommentLive(comment.id, liveId)} sx={{ position: "absolute", right: 0, padding: 1 }} size="small">
+                        <IconButton onClick={async () => await unpinCommentLive(comment.id as string, liveId)} sx={{ position: "absolute", right: 0, padding: 1 }} size="small">
                             <Iconify style={{ color: 'gray', marginBottom: 2 }} width={20} icon="ic:baseline-pin-off" />
                         </IconButton>
                     </Card>
diff --git a/src/shared/sections/lives/supervision/details-comments-item.tsx b/src/shared/sections/lives/supervision/details-comments-item.tsx
index 400f06d2..935c43bd 100644
--- a/src/shared/sections/lives/supervision/details-comments-item.tsx
+++ b/src/shared/sections/lives/supervision/details-comments-item.tsx
@@ -1,34 +1,23 @@
-import { formatDistanceToNowStrict } from 'date-fns';
-
 import Stack from '@mui/material/Stack';
 import IconButton from '@mui/material/IconButton';
 import Typography from '@mui/material/Typography';
-
-
 import Iconify from '@/components/iconify';
-
 import { ILiveComment } from '@/shared/types/live';
 import { Card, useTheme, alpha } from '@mui/material';
-import { bgGradient } from '@/shared/theme/css';
 import { useResponsive } from '@/hooks';
 import { deleteCommentLive, pinCommentLive } from '@/shared/api/live';
 
-
-
 type Props = {
   comment: ILiveComment;
   changeParentComment: (comment: ILiveComment) => void;
-
 };
 
 export default function LiveCommentItem({ comment, changeParentComment }: Props) {
-
-  const { content, senderName, parent , admin} = comment;
+  const { content, senderName, parent, admin } = comment;
   const theme = useTheme();
   const mdUp = useResponsive('up', 'md');
   const bgStyle = mdUp ? {
-
-    backgroundColor: !admin ? alpha(theme.palette['primary'].main, 0.2) : alpha(theme.palette.secondary.dark, 0.2) ,
+    backgroundColor: !admin ? alpha(theme.palette['primary'].main, 0.2) : alpha(theme.palette.secondary.dark, 0.2),
     width: "100%",
     p: .5,
     fontSize: theme.typography.pxToRem(12),
@@ -41,9 +30,6 @@ export default function LiveCommentItem({ comment, changeParentComment }: Props)
     p: .5,
   };
 
-
-
-
   const renderInfo = (
     <Typography
       noWrap
@@ -54,7 +40,6 @@ export default function LiveCommentItem({ comment, changeParentComment }: Props)
       }}
     >
       {senderName} 
-    
     </Typography>
   );
 
@@ -111,7 +96,6 @@ export default function LiveCommentItem({ comment, changeParentComment }: Props)
     </Card>
   );
 
-
   const renderActions = (
     <Stack
       direction="row"
@@ -131,10 +115,10 @@ export default function LiveCommentItem({ comment, changeParentComment }: Props)
       <IconButton onClick={() => changeParentComment(comment)} size="small">
         <Iconify icon="solar:reply-bold" width={16} />
       </IconButton>
-      <IconButton onClick={() => deleteCommentLive(comment.id, comment.liveStream)} size="small">
+      <IconButton onClick={() => deleteCommentLive(comment.id as string, comment.liveStream)} size="small">
         <Iconify icon="material-symbols:delete" width={16} />
       </IconButton>
-      <IconButton onClick={() => pinCommentLive(comment.id, comment.liveStream)} size="small">
+      <IconButton onClick={() => pinCommentLive(comment.id as string, comment.liveStream)} size="small">
         <Iconify icon="mdi:pin" width={16} />
       </IconButton>
     </Stack>
@@ -144,8 +128,6 @@ export default function LiveCommentItem({ comment, changeParentComment }: Props)
     <Stack direction="column" justifyContent={'unset'} sx={{ mb: 2 }}>
       <Stack alignItems="flex-end">
         {renderInfo}
-
-
       </Stack>
       <Stack
         direction="row"
diff --git a/src/shared/sections/lives/supervision/details-comments-list.tsx b/src/shared/sections/lives/supervision/details-comments-list.tsx
index 80a1c989..0e8d375c 100644
--- a/src/shared/sections/lives/supervision/details-comments-list.tsx
+++ b/src/shared/sections/lives/supervision/details-comments-list.tsx
@@ -1,18 +1,40 @@
 "use client";
 
 import React, { useEffect, useRef } from 'react';
-import { Box } from '@mui/material';
+import { Box, IconButton } from '@mui/material';
 import Scrollbar from '@/shared/components/scrollbar';
 import LiveCommentItem from './details-comments-item';
 import { ILiveComment } from '@/shared/types/live';
 import useLiveComments from '@/hooks/use-live-comments';
 import { useLiveData } from '@/contexts/live-stats';
+import { useResponsive } from '@/hooks';
+import Iconify from '@/components/iconify';
+import { parse } from 'json2csv';
 
 export default function CommentsList({ changeParentComment }: { changeParentComment: (comment: ILiveComment | null) => void }) {
   const liveData = useLiveData();
-  const { comments, pinnedComments } = useLiveComments(liveData);
+  const { comments } = useLiveComments(liveData);
   const latestCommentRef = useRef<HTMLDivElement | null>(null);
   const scrollbarRef = useRef<HTMLDivElement>();
+  const mdUp = useResponsive('up', 'md');
+
+  const handleExportComments = () => {
+    const fields = ['senderName', 'content']; // specify the fields you want in the CSV
+    const opts = { fields };
+    try {
+      const csv = parse(comments, opts);
+      const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
+      const url = URL.createObjectURL(blob);
+      const a = document.createElement('a');
+      a.href = url;
+      a.download = 'comments.csv';
+      document.body.appendChild(a);
+      a.click();
+      a.remove();
+    } catch (err) {
+      console.error('Error converting JSON to CSV', err);
+    }
+  };
 
   useEffect(() => {
     if (latestCommentRef.current && scrollbarRef.current) {
@@ -21,31 +43,28 @@ export default function CommentsList({ changeParentComment }: { changeParentComm
   }, [comments]);
 
   return (
-    <Scrollbar sx={{ px: 2, py: 5, height: 1, color: 'transparent' }}>
-      <Box sx={{ position: 'relative' }}>
-        {/* <Scrollbar sx={{ px: 2, py: 5, height: 1, color: 'transparent' }}>
-          <Box sx={{ height: 300, zIndex: 4, overflow: 'hidden', position: 'absolute', left: 0, right: 0, top: 0, bottom: 0 }}>
-            {pinnedComments.map((comment) => (
-              <LiveCommentItem
-                changeParentComment={changeParentComment}
-                key={comment.id}
-                comment={comment}
-              />
-            ))
-            }
-          </Box>
-        </Scrollbar> */}
-
-        {comments.map((comment) => (
-          <LiveCommentItem
-            changeParentComment={changeParentComment}
-            key={comment.id}
-            comment={comment}
+    <>
+      {mdUp && (
+        <IconButton
+          onClick={handleExportComments}
+          sx={{ position: 'absolute', color: 'white', bgcolor: 'black', zIndex: 2, top: 20, right: 20 }}
+        >
+          <Iconify icon="solar:download-bold" />
+        </IconButton>
+      )}
+      <Scrollbar sx={{ px: 2, height: 1, position: 'relative', color: 'transparent' }}>
 
-          />
-        ))}
-        <div ref={latestCommentRef} />
-      </Box>
-    </Scrollbar>
+        <Box sx={{ position: 'relative', py: 10 }}>
+          {comments.map((comment) => (
+            <LiveCommentItem
+              changeParentComment={changeParentComment}
+              key={comment.id}
+              comment={comment}
+            />
+          ))}
+          <div ref={latestCommentRef} />
+        </Box>
+      </Scrollbar>
+    </>
   );
 }
diff --git a/src/shared/sections/lives/supervision/details-comments-section.tsx b/src/shared/sections/lives/supervision/details-comments-section.tsx
index 1e6c86ff..3668b41d 100644
--- a/src/shared/sections/lives/supervision/details-comments-section.tsx
+++ b/src/shared/sections/lives/supervision/details-comments-section.tsx
@@ -1,9 +1,10 @@
 import { useResponsive } from "@/hooks/use-responsive";
-import { Box, Card, Grid } from "@mui/material";
+import { Box, Button, Card, Grid } from "@mui/material";
 import CommentsInput from "./details-comments-input";
 import CommentsList from "./details-comments-list";
 import { ILiveComment } from "@/shared/types/live";
 import { useState } from "react";
+import useLiveComments from "@/hooks/use-live-comments";
 
 type Props = {
     liveId: string,
@@ -12,6 +13,8 @@ type Props = {
 export default function CommentSection({ liveId }: Props) {
     const mdUp = useResponsive('up', 'md');
     const [parentComment, setParentComment] = useState<ILiveComment | null>(null);
+   
+    
 
     return (
         <>
diff --git a/src/shared/sections/lives/supervision/details-player-section.tsx b/src/shared/sections/lives/supervision/details-player-section.tsx
index 9d033cfd..111fc343 100644
--- a/src/shared/sections/lives/supervision/details-player-section.tsx
+++ b/src/shared/sections/lives/supervision/details-player-section.tsx
@@ -5,7 +5,8 @@ import { ConfirmDialog } from "@/shared/components/custom-dialog";
 import { LiveStatus } from "@/shared/types/live";
 import LoadingButton from "@mui/lab/LoadingButton";
 import { Card, Grid } from "@mui/material";
-import ReactPlayer from 'react-player'
+import ReactPlayer from 'react-player';
+import { useRef, useEffect } from 'react';
 
 type Props = {
     keyStream: string | undefined;
@@ -17,10 +18,10 @@ type Props = {
 };
 
 export default function VideoPlayerSection({ keyStream, hlsServerAddress, status, liveId, videoLink }: Props) {
-    const liveUrl = status!= LiveStatus.ONGOING ? videoLink : `${hlsServerAddress}/${keyStream}.m3u8`;
+    const liveUrl = status != LiveStatus.ONGOING ? videoLink : `${hlsServerAddress}/${keyStream}.m3u8`;
     const startConfirm = useBoolean();
-    console.log( "status != LiveStatus.COMING =",status != LiveStatus.COMING)
-    console.log(liveUrl);
+    const playerRef = useRef<ReactPlayer>(null);
+
     const handleStart = async () => {
         try {
             await startLive(liveId);
@@ -28,30 +29,63 @@ export default function VideoPlayerSection({ keyStream, hlsServerAddress, status
         } catch (error) {
             console.error(error);
         }
-    }
+    };
+
+    const handleEnablePiP = () => {
+        if (playerRef.current) {
+            const internalPlayer = playerRef.current.getInternalPlayer();
+            if (internalPlayer && internalPlayer.requestPictureInPicture) {
+                internalPlayer.requestPictureInPicture();
+            }
+        }
+    };
+
+    useEffect(() => {
+        const interval = setInterval(() => {
+            const pipButton = document.querySelector('button[aria-label="Picture-in-Picture"]');
+            if (pipButton) {
+                pipButton.textContent = 'Réduire';
+                clearInterval(interval);
+            }
+        }, 1000);
+
+        return () => clearInterval(interval);
+    }, []);
+
     return (
         <Grid item lg={4} md={8} xs={12}>
             <Card sx={{ position: "relative", height: 600, zIndex: 0, p: 0, bgcolor: 'black', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
-                {status != LiveStatus.COMING
-                    && <ReactPlayer playing={true}
+                {status != LiveStatus.COMING &&
+                    <ReactPlayer
+                        ref={playerRef}
+                        playing={true}
                         controls={true}
+                        pip={true}
                         width="100%"
-                        height="100%" url={liveUrl} />
+                        height="100%"
+                        url={liveUrl}
+                    />
+                }
+                {status == LiveStatus.COMING &&
+                    <Iconify
+                        color='white'
+                        sx={{ position: "absolute", margin: "auto", width: 100, height: 100, cursor: 'pointer' }}
+                        onClick={startConfirm.onTrue}
+                        icon="solar:play-bold"
+                    />
                 }
-                {status == LiveStatus.COMING && <Iconify color='white' sx={{ position: "absolute", margin: "auto", width: 100, height: 100, cursor: 'pointer' }} onClick={startConfirm.onTrue} icon="solar:play-bold" />}
             </Card>
             <ConfirmDialog
                 open={startConfirm.value}
                 onClose={startConfirm.onFalse}
                 title="démarrer"
-                content="Voulez-vous démarrer  ce live?"
+                content="Voulez-vous démarrer ce live?"
                 action={
                     <LoadingButton variant="contained" color="warning" onClick={handleStart}>
                         démarrer
                     </LoadingButton>
                 }
             />
-
         </Grid>
-    )
-}
\ No newline at end of file
+    );
+}
diff --git a/src/shared/sections/lives/supervision/details-product-card.tsx b/src/shared/sections/lives/supervision/details-product-card.tsx
index ecf39a2c..a8ff0938 100644
--- a/src/shared/sections/lives/supervision/details-product-card.tsx
+++ b/src/shared/sections/lives/supervision/details-product-card.tsx
@@ -1,22 +1,27 @@
 "use client";
 
-import React, { useState, useCallback } from 'react';
+import React, { useState, useCallback, useEffect } from 'react';
 import {
     Avatar,
     Box,
     Button,
     Card,
     Grid,
+    IconButton,
     ListItemText,
+    MenuItem,
     useTheme,
 } from '@mui/material';
 import { TimeField } from '@mui/x-date-pickers';
 import Iconify from '@/components/iconify';
 import {
-    addProductLive,
+    addTimeStampProduct,
     deleteProductLive,
+    deleteTimeStampProduct,
     hideProductLive,
+    presentProductLive,
     pushProductLive,
+    updateTimeStampProduct,
 } from '@/shared/api/live';
 import {
     calculateSeconds,
@@ -24,10 +29,18 @@ import {
     secondsToTime,
 } from '@/utils/format-time';
 import { useLiveData } from '@/contexts/live-stats';
-import { LiveProductStatus, LiveStatus } from '@/shared/types/live';
+import { LiveProductStatus, LiveStatus, TimeStampProduct } from '@/shared/types/live';
 import { useSnackbar } from '@/components/snackbar';
+import EditIcon from '@mui/icons-material/Edit';
+import DeleteIcon from '@mui/icons-material/Delete';
+import BookmarkIcon from '@mui/icons-material/Bookmark';
+import AddIcon from '@mui/icons-material/Add';
+import useAsync from '@/hooks/use-async';
+import LoadingButton from '@mui/lab/LoadingButton';
+import CustomPopover, { usePopover } from '@/shared/components/custom-popover';
 
-type Props = {
+
+type ProductCardProps = {
     liveId: string;
     id: string;
     title: string;
@@ -35,60 +48,174 @@ type Props = {
     sku: string;
     image: string;
     price: number;
-    startTime?: number | undefined;
-    endTime?: number | undefined;
+    timeStampProduct: TimeStampProduct[];
+};
+
+type TimeStampProductFiledProps = {
+    liveProductId: string;
+    liveId: string;
+    id?: string;
+    initialStartTime?: number;
+    initialEndTime?: number;
+    status: LiveProductStatus;
+};
+
+const TimeStampProductFiled = ({ id, initialStartTime, initialEndTime, status, liveId, liveProductId }: TimeStampProductFiledProps) => {
+    const [startTime, setStartTime] = useState<number | undefined>(initialStartTime);
+    const [endTime, setEndTime] = useState<number | undefined>(initialEndTime);
+    const [modify, setModify] = useState<boolean>(false);
+    const popover = usePopover();
+
+    useEffect(() => {
+        console.log('initialStartTime', { id, initialStartTime, initialEndTime, status, liveId, liveProductId });
+    }, []);
+
+    const { loading: deleting, execute: handleDeleteTimeStampProduct } = useAsync(async () => {
+        await deleteTimeStampProduct(id as string);
+    });
+
+    const { loading: updating, execute: handleUpdateTimeStampProduct } = useAsync(async () => {
+        await updateTimeStampProduct(id as string, startTime as number, endTime as number);
+        setModify(false);
+    });
+
+    const { loading: adding, execute: handleAddTimeStampProduct } = useAsync(async () => {
+        await addTimeStampProduct(liveId, liveProductId, startTime as number, endTime as number);
+        setModify(false);
+        setStartTime(undefined);
+        setEndTime(undefined);
+    });
+
+    return (
+        <Box sx={{ display: 'flex', width: '100%', justifyContent: 'start', gap: 2 }}>
+            <TimeField
+                value={startTime && secondsToTime(startTime)}
+                onChange={(date) => setStartTime(calculateSeconds(date as Date))}
+                disabled={id != undefined && !modify}
+                fullWidth
+
+                size="small"
+                label="Start Time"
+                InputLabelProps={{
+                    shrink: true,
+                    style: { fontSize: '0.8rem', }
+                }}
+                inputProps={{
+
+                    step: 1,
+                    style: { fontSize: '0.8rem', textAlign: 'center', height: 10, width:200 }
+                }}
+                sx={{ width: 200 }}
+                ampm={false}
+                format="HH:mm:ss"
+            />
+
+            <TimeField
+                fullWidth
+                size="small"
+                label="End Time"
+                onChange={(date) => setEndTime(calculateSeconds(date as Date))}
+                value={endTime && secondsToTime(endTime)}
+                disabled={id != undefined && !modify}
+                InputLabelProps={{
+                    shrink: true,
+                    style: { fontSize: '0.8rem' },
+                }}
+                inputProps={{
+                    step: 1,
+                    style: { fontSize: '0.8rem', textAlign: 'center', height: 10 , width:200 }
+                }}
+                sx={{ width: 200 }}
+                ampm={false}
+                format="HH:mm:ss"
+            />
+
+            <CustomPopover
+                open={popover.open}
+                onClose={popover.onClose}
+                arrow="right-top"
+                sx={{ width: 160 }}
+            >
+                <MenuItem
+                    onClick={() => {
+                        setModify(true);
+                        popover.onClose();
+
+                    }}
+
+                >
+                    <LoadingButton loading={updating}  >
+                        <EditIcon /> modifier
+                    </LoadingButton>
+                </MenuItem>
+                <MenuItem
+                    onClick={() => {
+                        handleDeleteTimeStampProduct();
+                    }}
+
+                >
+                    <LoadingButton loading={deleting}  >
+                        <DeleteIcon /> supprimer
+                    </LoadingButton>
+                </MenuItem>
+            </CustomPopover>
+
+
+            {id != undefined ? (
+                <>
+                    {modify ? (
+                        <LoadingButton loading={updating} onClick={handleUpdateTimeStampProduct} disabled={updating}>
+                            <Iconify icon="dashicons:saved" />
+                        </LoadingButton>
+                    ) : (
+                        <IconButton color={popover.open ? 'inherit' : 'default'} onClick={popover.onOpen}>
+                            <Iconify icon="eva:more-vertical-fill" />
+                        </IconButton>
+                    )}
+                </>
+            ) : (
+                <LoadingButton onClick={handleAddTimeStampProduct} loading={adding} disabled={adding}>
+                    <Iconify icon="carbon:add-filled" />
+                </LoadingButton>
+            )}
+        </Box>
+    );
 };
 
-const ProductCard: React.FC<Props> = ({
+const ProductCard: React.FC<ProductCardProps> = ({
     liveId,
     id,
     title,
     status,
     sku,
     image,
-    price,
-    startTime: initialStartTime,
-    endTime: initialEndTime,
+    timeStampProduct = [],
 }) => {
     const theme = useTheme();
     const { enqueueSnackbar } = useSnackbar();
     const { startedAt, status: liveStatus } = useLiveData();
-    const [startTime, setStartTime] = useState<number | undefined>(initialStartTime);
-    const [endTime, setEndTime] = useState<number | undefined>(initialEndTime);
-    const [modify, setModify] = useState<boolean>(false);
 
-    const handleAddProduct = useCallback(() => {
-        addProductLive(liveId, id, startTime as number, endTime as number);
-        setModify(false);
-    }, [liveStatus, status, liveId, id, startTime, endTime, enqueueSnackbar]);
-
-    const handlePushProduct = useCallback(() => {
+    const { loading: pushing, execute: handlePushProduct } = useAsync(async () => {
         if (status === LiveProductStatus.NOT_PRESENTED) {
-            pushProductLive(
-                id,
-                liveId,
-                differenceInSeconds(new Date(), new Date(startedAt as Date))
-            );
+            await presentProductLive(id, liveId, differenceInSeconds(new Date(), new Date(startedAt as Date)));
+        } else if (status === LiveProductStatus.PRESENTED) {
+            await pushProductLive(id, liveId, differenceInSeconds(new Date(), new Date(startedAt as Date)));
         } else {
             enqueueSnackbar('Produit déjà présenté', { variant: 'warning' });
         }
-    }, [status, id, liveId, startedAt, enqueueSnackbar]);
+    });
 
-    const handleHideProduct = useCallback(() => {
+    const { loading: hiding, execute: handleHideProduct } = useAsync(async () => {
         if (status === LiveProductStatus.IN_PRESENTATION) {
-            hideProductLive(
-                id,
-                liveId,
-                differenceInSeconds(new Date(), new Date(startedAt as Date))
-            );
+            await hideProductLive(id, liveId, differenceInSeconds(new Date(), new Date(startedAt as Date)));
         } else {
             enqueueSnackbar('Produit déjà caché', { variant: 'warning' });
         }
-    }, [status, id, liveId, startedAt, enqueueSnackbar]);
+    });
 
-    const handleDeleteProduct = useCallback(() => {
-        deleteProductLive(id, liveId);
-    }, [id, liveId]);
+    const { loading: deleting, execute: handleDeleteProduct } = useAsync(async () => {
+        await deleteProductLive(id, liveId);
+    });
 
     return (
         <Card variant="outlined" sx={{ marginBottom: 2, bgcolor: theme.palette.background.neutral }}>
@@ -115,103 +242,50 @@ const ProductCard: React.FC<Props> = ({
                     <Box sx={{ display: 'flex', width: '100%', justifyContent: 'space-between', gap: 2 }}>
                         {liveStatus === LiveStatus.ONGOING && (
                             <>
-                                {status === LiveProductStatus.NOT_PRESENTED && (
-                                    <Button variant="contained" fullWidth onClick={handlePushProduct}>
+                                {(status === LiveProductStatus.NOT_PRESENTED || status === LiveProductStatus.PRESENTED) && (
+                                    <LoadingButton loading={pushing} variant="contained" fullWidth onClick={handlePushProduct} disabled={pushing}>
                                         Pousser
-                                    </Button>
+                                    </LoadingButton>
                                 )}
                                 {status === LiveProductStatus.IN_PRESENTATION && (
-                                    <Button variant="contained" color="info" fullWidth onClick={handleHideProduct}>
+                                    <LoadingButton loading={hiding} variant="contained" color="info" fullWidth onClick={handleHideProduct} disabled={hiding}>
                                         Cacher
-                                    </Button>
-                                )}
-                                {status === LiveProductStatus.PRESENTED && (
-                                    <Button variant="contained" color="success" fullWidth disabled>
-                                        Présenté
-                                    </Button>
-                                )}
-                            </>
-                        )}
-                        {(liveStatus === LiveStatus.REVIEW || liveStatus === LiveStatus.REPLAY) && (
-                            <>
-                                {status !== LiveProductStatus.PRESENTED && (
-                                    <Button variant="contained" color="info" fullWidth onClick={handleAddProduct}>
-                                        Ajouter
-                                    </Button>
-                                )}
-                                {status === LiveProductStatus.PRESENTED && (
-                                    <>
-                                        {modify ? (
-                                            <Button
-                                                variant="contained"
-                                                color="success"
-                                                fullWidth
-                                                onClick={handleAddProduct}
-                                            >
-                                                Approuver
-                                            </Button>
-                                        ) : (
-                                            <Button
-                                                variant="contained"
-                                                color="error"
-                                                fullWidth
-                                                onClick={() => setModify(true)}
-                                            >
-                                                Modifier
-                                            </Button>
-                                        )}
-                                    </>
+                                    </LoadingButton>
                                 )}
                             </>
                         )}
-                        <Button
+                        <LoadingButton
                             onClick={handleDeleteProduct}
                             variant="contained"
                             fullWidth
                             startIcon={<Iconify icon="ic:round-delete" />}
+                            disabled={deleting}
+                            loading={deleting}
+
                         >
                             Supprimer
-                        </Button>
+                        </LoadingButton>
                     </Box>
                     {(liveStatus === LiveStatus.REVIEW || liveStatus === LiveStatus.REPLAY) && (
-                        <Box sx={{ display: 'flex', width: '100%', justifyContent: 'space-between', gap: 2 }}>
-                            <TimeField
-                                value={startTime && secondsToTime(startTime)}
-                                onChange={(date) => setStartTime(calculateSeconds(date as Date))}
-                                disabled={
-                                    (status === LiveProductStatus.PRESENTED && !modify)
-                                }
-                                fullWidth
-                                size="small"
-                                label="Start Time"
-                                InputLabelProps={{
-                                    shrink: true,
-                                }}
-                                inputProps={{
-                                    step: 1,
-                                }}
-                                ampm={false}
-                                format="HH:mm:ss"
-                            />
-                            <TimeField
-                                fullWidth
-                                size="small"
-                                label="End Time"
-                                onChange={(date) => setEndTime(calculateSeconds(date as Date))}
-                                value={endTime && secondsToTime(endTime)}
-                                disabled={
-                                    (status === LiveProductStatus.PRESENTED && !modify)
-                                }
-                                InputLabelProps={{
-                                    shrink: true,
-                                }}
-                                inputProps={{
-                                    step: 1,
-                                }}
-                                ampm={false}
-                                format="HH:mm:ss"
+                        <>
+                            {timeStampProduct.map((timeStamp) => (
+                                <TimeStampProductFiled
+                                    key={timeStamp.id}
+                                    id={timeStamp.id}
+                                    initialStartTime={timeStamp.startTime}
+                                    initialEndTime={timeStamp.endTime}
+                                    status={status}
+                                    liveId={liveId}
+                                    liveProductId={id}
+                                />
+                            ))}
+                            <TimeStampProductFiled
+                                key={-1}
+                                status={status}
+                                liveId={liveId}
+                                liveProductId={id}
                             />
-                        </Box>
+                        </>
                     )}
                 </Grid>
             </Grid>
diff --git a/src/shared/sections/lives/supervision/details-products-section.tsx b/src/shared/sections/lives/supervision/details-products-section.tsx
index 57330f9e..fc28a95e 100644
--- a/src/shared/sections/lives/supervision/details-products-section.tsx
+++ b/src/shared/sections/lives/supervision/details-products-section.tsx
@@ -7,6 +7,7 @@ import { useState } from "react";
 import { addProductToLive, getProductsLive, searchProductLive } from "@/shared/api/live";
 import { ILiveProduct } from "@/shared/types/live";
 import LiveSearch from "./details-add-product";
+import { usePopover } from "@/shared/components/custom-popover";
 
 type Props = {
     liveId: string;
@@ -16,6 +17,7 @@ export default function ProductsSection({ liveId }: Props) {
     const lgUp = useResponsive('up', 'lg');
 
     const { products } = getProductsLive(liveId);
+    const popover = usePopover();
 
     const { endRef: productsEndRef } = useScroll(products);
     const [open, setOpen] = useState(false);
@@ -47,7 +49,7 @@ export default function ProductsSection({ liveId }: Props) {
     return (
         <>
             {lgUp ? (
-                <Grid spacing={0} item lg={4} md={6} xs={12}>
+                <Grid item lg={4} md={6} xs={12}>
                     <LiveSearch
                         query={query}
                         results={searchResults}
diff --git a/src/shared/sections/lives/supervision/view.tsx b/src/shared/sections/lives/supervision/view.tsx
index 708a0b5c..ca5b75d3 100644
--- a/src/shared/sections/lives/supervision/view.tsx
+++ b/src/shared/sections/lives/supervision/view.tsx
@@ -1,17 +1,13 @@
 'use client';
 
-import { useSettingsContext } from '@/shared/components/settings';
-import { Grid, Container, Card } from '@mui/material';
+import { Grid, Container } from '@mui/material';
 import CommentSection from './details-comments-section';
 import ProductsSection from './details-products-section';
 import VideoPlayerSection from './details-player-section';
 import HeadSection from './details-head-section';
-import { useGetLive } from '@/shared/api/live';
 import { useLiveData } from '@/contexts/live-stats';
 
-type Props = {
-    liveId: string;
-}
+
 
 export default function LiveDetailsView() {
     const liveData = useLiveData();
diff --git a/src/shared/types/live.ts b/src/shared/types/live.ts
index 7a7e01f0..0a7f9b62 100644
--- a/src/shared/types/live.ts
+++ b/src/shared/types/live.ts
@@ -70,7 +70,12 @@ export type ILiveComment = {
 }
 
 
-
+export type TimeStampProduct = {
+  id: string;
+  startTime?: number;
+  endTime?: number;
+  liveProductId?: string;
+}
 
 export type ILiveProduct = {
   id: string;
@@ -78,9 +83,9 @@ export type ILiveProduct = {
   sku: string;
   image: string;
   price: number;
+  isPresented: boolean;
   status: LiveProductStatus;
-  startTime?: number;
-  endTime?: number;
+  timeStampProduct: TimeStampProduct[];
 }
 
 export type ILiveStatistic = {
-- 
GitLab