From d7764faf157cd9545363db95a428f211f23249cc Mon Sep 17 00:00:00 2001
From: Nevo David <me@nevos.io>
Date: Thu, 6 Feb 2025 23:15:50 +0700
Subject: [PATCH 1/3] feat: send tests

---
 .../src/api/routes/webhooks.controller.ts     | 26 +++++-
 .../src/components/webhooks/webhooks.tsx      | 81 ++++++++++++++++---
 .../prisma/webhooks/webhooks.service.ts       | 10 ++-
 3 files changed, 102 insertions(+), 15 deletions(-)

diff --git a/apps/backend/src/api/routes/webhooks.controller.ts b/apps/backend/src/api/routes/webhooks.controller.ts
index 19a787301..6b341d6ab 100644
--- a/apps/backend/src/api/routes/webhooks.controller.ts
+++ b/apps/backend/src/api/routes/webhooks.controller.ts
@@ -1,4 +1,13 @@
-import { Body, Controller, Delete, Get, Param, Post, Put } from '@nestjs/common';
+import {
+  Body,
+  Controller,
+  Delete,
+  Get,
+  Param,
+  Post,
+  Put,
+  Query,
+} from '@nestjs/common';
 import { GetOrgFromRequest } from '@gitroom/nestjs-libraries/user/org.from.request';
 import { Organization } from '@prisma/client';
 import { ApiTags } from '@nestjs/swagger';
@@ -47,4 +56,19 @@ export class WebhookController {
   ) {
     return this._webhooksService.deleteWebhook(org.id, id);
   }
+
+  @Post('/send')
+  async sendWebhook(@Body() body: any, @Query('url') url: string) {
+    try {
+      await fetch(url, {
+        method: 'POST',
+        body: JSON.stringify(body),
+        headers: { 'Content-Type': 'application/json' },
+      });
+    } catch (err) {
+      /** sent **/
+    }
+
+    return { send: true };
+  }
 }
diff --git a/apps/frontend/src/components/webhooks/webhooks.tsx b/apps/frontend/src/components/webhooks/webhooks.tsx
index 6d964d99a..a1792854f 100644
--- a/apps/frontend/src/components/webhooks/webhooks.tsx
+++ b/apps/frontend/src/components/webhooks/webhooks.tsx
@@ -175,6 +175,51 @@ export const AddOrEditWebhook: FC<{ data?: any; reload: () => void }> = (
     [data, integrations]
   );
 
+  const sendTest = useCallback(async () => {
+    const url = form.getValues('url');
+    toast.show('Webhook send', 'success');
+    try {
+      await fetch(`/webhooks/send?url=${encodeURIComponent(url)}`, {
+        method: 'POST',
+        headers: {
+          contentType: 'application/json',
+        },
+        body: JSON.stringify([
+          {
+            id: 'cm6tcts4f0005qcwit25cis26',
+            content: 'This is the first post to instagram',
+            publishDate: '2025-02-06T13:09:00.000Z',
+            releaseURL: 'https://facebook.com/release/release',
+            state: 'PUBLISHED',
+            integration: {
+              id: 'cm6s4uyou0001i2r47pxix6z1',
+              name: 'test',
+              providerIdentifier: 'instagram',
+              picture: 'https://uploads.gitroom.com/F6LSCD8wrrQ.jpeg',
+              type: 'social',
+            },
+          },
+          {
+            id: 'cm6tcts4f0005qcwit25cis26',
+            content: 'This is the second post to facebook',
+            publishDate: '2025-02-06T13:09:00.000Z',
+            releaseURL: 'https://facebook.com/release2/release2',
+            state: 'PUBLISHED',
+            integration: {
+              id: 'cm6s4uyou0001i2r47pxix6z1',
+              name: 'test2',
+              providerIdentifier: 'facebook',
+              picture: 'https://uploads.gitroom.com/F6LSCD8wrrQ.jpeg',
+              type: 'social',
+            },
+          },
+        ]),
+      });
+    } catch (e: any) {
+      /** empty **/
+    }
+  }, []);
+
   return (
     <FormProvider {...form}>
       <form onSubmit={form.handleSubmit(callBack)}>
@@ -227,16 +272,32 @@ export const AddOrEditWebhook: FC<{ data?: any; reload: () => void }> = (
                 isMain={true}
               />
             )}
-            <Button
-              type="submit"
-              className="mt-[24px]"
-              disabled={
-                !form.formState.isValid ||
-                (allIntegrations.value === 'specific' && !integrations?.length)
-              }
-            >
-              Save
-            </Button>
+            <div className="flex gap-[10px]">
+              <Button
+                type="submit"
+                className="mt-[24px]"
+                disabled={
+                  !form.formState.isValid ||
+                  (allIntegrations.value === 'specific' &&
+                    !integrations?.length)
+                }
+              >
+                Save
+              </Button>
+              <Button
+                type="button"
+                secondary={true}
+                className="mt-[24px]"
+                onClick={sendTest}
+                disabled={
+                  !form.formState.isValid ||
+                  (allIntegrations.value === 'specific' &&
+                    !integrations?.length)
+                }
+              >
+                Send Test
+              </Button>
+            </div>
           </div>
         </div>
       </form>
diff --git a/libraries/nestjs-libraries/src/database/prisma/webhooks/webhooks.service.ts b/libraries/nestjs-libraries/src/database/prisma/webhooks/webhooks.service.ts
index d23bed29a..54672b5e2 100644
--- a/libraries/nestjs-libraries/src/database/prisma/webhooks/webhooks.service.ts
+++ b/libraries/nestjs-libraries/src/database/prisma/webhooks/webhooks.service.ts
@@ -73,10 +73,12 @@ export class WebhooksService {
         );
       }
 
-      sendList.push({
-        url: webhook.url,
-        data: toSend,
-      });
+      if (toSend.length) {
+        sendList.push({
+          url: webhook.url,
+          data: toSend,
+        });
+      }
     }
 
     return Promise.all(

From d51196c5364a6ba84cadcdb0a403c86fb81f9c6a Mon Sep 17 00:00:00 2001
From: Nevo David <me@nevos.io>
Date: Thu, 6 Feb 2025 23:29:38 +0700
Subject: [PATCH 2/3] feat: settings

---
 .../components/layout/settings.component.tsx  | 25 ++++++++++++++++++-
 .../src/components/layout/top.menu.tsx        |  1 -
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/apps/frontend/src/components/layout/settings.component.tsx b/apps/frontend/src/components/layout/settings.component.tsx
index 8a6edf980..3ae40b934 100644
--- a/apps/frontend/src/components/layout/settings.component.tsx
+++ b/apps/frontend/src/components/layout/settings.component.tsx
@@ -21,6 +21,7 @@ import { useVariables } from '@gitroom/react/helpers/variable.context';
 import { PublicComponent } from '@gitroom/frontend/components/public-api/public.component';
 import Link from 'next/link';
 import { Webhooks } from '@gitroom/frontend/components/webhooks/webhooks';
+import { TopTitle } from '@gitroom/frontend/components/launches/helpers/top.title.component';
 
 export const SettingsPopup: FC<{ getRef?: Ref<any> }> = (props) => {
   const { isGeneral } = useVariables();
@@ -210,8 +211,30 @@ export const SettingsPopup: FC<{ getRef?: Ref<any> }> = (props) => {
 };
 
 export const SettingsComponent = () => {
+  const settings = useModals();
+  const user = useUser();
+
+  const openModal = useCallback(() => {
+    if (user?.tier.current !== 'FREE') {
+      return;
+    }
+
+    settings.openModal({
+      children: (
+        <div className="relative flex gap-[20px] flex-col flex-1 rounded-[4px] border border-customColor6 bg-sixth p-[16px] w-[500px] mx-auto">
+          <SettingsPopup />
+        </div>
+      ),
+      classNames: {
+        modal: 'bg-transparent text-textColor',
+      },
+      withCloseButton: false,
+      size: '100%',
+    });
+  }, [user]);
+
   return (
-    <Link href="/settings">
+    <Link href="/settings" onClick={openModal}>
       <svg
         width="40"
         height="40"
diff --git a/apps/frontend/src/components/layout/top.menu.tsx b/apps/frontend/src/components/layout/top.menu.tsx
index f4bc2f373..b3483eefc 100644
--- a/apps/frontend/src/components/layout/top.menu.tsx
+++ b/apps/frontend/src/components/layout/top.menu.tsx
@@ -77,7 +77,6 @@ export const TopMenu: FC = () => {
   const user = useUser();
   const { billingEnabled } = useVariables();
   const menuItems = useMenuItems();
-
   return (
     <div className="flex flex-col h-full animate-normalFadeDown order-3 md:order-2 col-span-2 md:col-span-1">
       <ul className="gap-0 md:gap-5 flex flex-1 items-center text-[18px]">

From 379704c997c117d68533d57043f9f78b4a234a4a Mon Sep 17 00:00:00 2001
From: Nevo David <me@nevos.io>
Date: Fri, 7 Feb 2025 18:33:12 +0700
Subject: [PATCH 3/3] feat: fix

---
 .../integrations/social/instagram.provider.ts | 36 ++++++++++++++++---
 1 file changed, 31 insertions(+), 5 deletions(-)

diff --git a/libraries/nestjs-libraries/src/integrations/social/instagram.provider.ts b/libraries/nestjs-libraries/src/integrations/social/instagram.provider.ts
index fd787a921..c548a7755 100644
--- a/libraries/nestjs-libraries/src/integrations/social/instagram.provider.ts
+++ b/libraries/nestjs-libraries/src/integrations/social/instagram.provider.ts
@@ -383,21 +383,47 @@ export class InstagramProvider
     const since = dayjs().subtract(date, 'day').unix();
 
     const { data, ...all } = await (
-      await fetch(
-        `https://graph.facebook.com/v20.0/${id}/insights?metric=follower_count,impressions,reach,profile_views&access_token=${accessToken}&period=day&since=${since}&until=${until}`
+      await this.fetch(
+        `https://graph.facebook.com/v20.0/${id}/insights?metric=follower_count,impressions,reach&access_token=${accessToken}&period=day&since=${since}&until=${until}`
+      )
+    ).json();
+
+    const { data: data2, ...all2 } = await (
+      await this.fetch(
+        `https://graph.facebook.com/v20.0/${id}/insights?metric_type=total_value&metric=likes,comments,shares,saves,replies&access_token=${accessToken}&period=day&since=${since}&until=${until}`
       )
     ).json();
+    const analytics = [];
 
-    return (
-      data?.map((d: any) => ({
+    analytics.push(
+      ...(data?.map((d: any) => ({
         label: d.title,
         percentageChange: 5,
         data: d.values.map((v: any) => ({
           total: v.value,
           date: dayjs(v.end_time).format('YYYY-MM-DD'),
         })),
-      })) || []
+      })) || [])
+    );
+
+    analytics.push(
+      ...data2.map((d: any) => ({
+        label: d.title,
+        percentageChange: 5,
+        data: [
+          {
+            total: d.total_value.value,
+            date: dayjs().format('YYYY-MM-DD'),
+          },
+          {
+            total: d.total_value.value,
+            date: dayjs().add(1, 'day').format('YYYY-MM-DD'),
+          },
+        ],
+      }))
     );
+
+    return analytics;
   }
 
   music(accessToken: string, data: { q: string }) {